package org.simpleframework.aop;

import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.ShadowMatch;

import java.lang.reflect.Method;


/**
 * 解析Aspect表达式并且定位被织入的目标
 *
 * @author: Oliver
 * @time: 2020/12/24/20:49
 */
public class PointcutLocator {

    /**
     * 表达式解析器
     */
    private PointcutExpression pointcutExpression;
    /**
     * Pointcut解析器，直接给它赋值上Aspectj的所有表达式，以便支持对众多表达式的解析
     */
    private PointcutParser pointcutParser = PointcutParser.
            getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(
                    PointcutParser.getAllSupportedPointcutPrimitives());

    /**
     * 构造器 传入表达式 Pointcut解析器解析成表达式解析器实例对象
     *
     * @param expression
     */
    public PointcutLocator(String expression) {
        this.pointcutExpression = pointcutParser.parsePointcutExpression(expression);
    }

    /**
     * 判断传入的Class对象是否是Aspect要代理的目标类，即匹配Pointcut表达式(初筛)
     *
     * @param targetClass 目标类
     * @return 是否匹配
     */
    public boolean roughMatches(Class<?> targetClass) {
        //couldMatchJoinPointsInType比较坑，只能校验within
        //不能校验 (execution(精确到某个类除外), call, get, set)，面对无法校验的表达式，直接返回true
        return pointcutExpression.couldMatchJoinPointsInType(targetClass);
    }

    /**
     * 判断传入的Method对象是否是Aspect的目标代理方法，即匹配Pointcut表达式(精筛)
     *
     * @param method
     * @return
     */
    public boolean accurateMatches(Method method) {
        //调用matchesMethodExecution判断是都为具体方法的织入
        ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
        if (shadowMatch.alwaysMatches()) {
            return true;
        } else {
            return false;
        }
    }
}
